package com.ltv.xiangqibook.web;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.ltv.xiangqibook.common.XiangQiBookConfiguration;


public class ConnectionPool {
	private static final Logger logger = LogManager.getLogger(ConnectionPool.class);
    private List<Connection> connections;
    private static ConnectionPool instance;
    
    private ConnectionPool() {
        connections = createConnections();
        
        Timer wakeUpConnectionsTimer = new Timer();
        TimerTask wakeUpConnectionsTask = new TimerTask() {
			
			@Override
			public void run() {
				try {
					wakeUpConnections();
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			}
		};
        
        long period = XiangQiBookConfiguration.getInstance().getWakeUpPeriod()*60*1000;
        wakeUpConnectionsTimer.schedule(wakeUpConnectionsTask, period, period);
    }

    private List<Connection> createConnections() {
        int connectionPoolSize = XiangQiBookConfiguration.getInstance().getConnectionPoolSize();
        List<Connection> conns = new ArrayList<Connection>(connectionPoolSize);
        for (int i = 0; i < connectionPoolSize; i++) {
            Connection con = null;
            try {
                Class.forName("com.mysql.jdbc.Driver");
                String dbURL = "jdbc:mysql://" + XiangQiBookConfiguration.getInstance().getDBHost();
                dbURL += ":" + XiangQiBookConfiguration.getInstance().getDBPort();
                dbURL += "/" + XiangQiBookConfiguration.getInstance().getDBName();
                dbURL += "?autoReconnect=true&useEncoding=true&characterEncoding=UTF-8";

                String dbUser = XiangQiBookConfiguration.getInstance().getDBUser();
                String dbPassword = XiangQiBookConfiguration.getInstance().getDBPassword();

                con = DriverManager.getConnection (dbURL, dbUser, dbPassword);
                conns.add(con);
            } catch (Exception e) {
            	logger.error(e.getMessage(), e);
            }
        }
        return conns;
    }
    
    private void wakeUpConnections() throws Exception {
    	logger.info("Start waking up all connections...");
    	synchronized (connections) {
    		Statement wakeUpStmt = null;
    		for (Connection con : connections) {
    			try {
	    			wakeUpStmt = con.createStatement();
	    			wakeUpStmt.execute(XiangQiBookConfiguration.getInstance().getWakeUpQuery());
    			} finally {
    				if (wakeUpStmt != null) {
    					wakeUpStmt.close();
    				}
    			}
    		}
    	}
    	logger.info("End waking up all connections.");
    }

    public Connection getConnection() throws InterruptedException {
        synchronized (connections) {
            while (connections.isEmpty()) {
                connections.wait();
            }
            return connections.remove(0);
        }
    }

    public void returnConnection(Connection conn) {
        synchronized (connections) {
            connections.add(conn);
            connections.notify();
        }
    }
    
    public void closeAllConnections() throws SQLException {
        if (connections != null) {
            for (Connection con : connections) {
                con.close();
            }
        }
    }

    public static ConnectionPool getInstance() {
        if (instance == null) {
            instance = new ConnectionPool();
        }
        
        return instance;
    }
    
}
